nanobook 0.14.0

Deterministic Rust execution engine for trading backtests: limit-order book, portfolio simulation, metrics, risk checks, and Python bindings
Documentation
# Plan: F4 - Stale Market Data Detection

## Goal
Add staleness detection to quotes. Rebalancer must detect when last_quote_age > threshold and abort the rebalance rather than trade on stale prices.

## Phase 1: Add Timestamp to Quote (verify: compiles)
- [ ] Add timestamp field (Instant or SystemTime) to Quote struct
- [ ] Update Quote construction in all broker implementations
- [ ] Update MockBroker to set current timestamp
- [ ] Update IBKR client to set timestamp when fetching quotes
- [ ] Update Binance client to set timestamp when fetching quotes

## Phase 2: Add Staleness Configuration (verify: config compiles)
- [ ] Add quote_staleness_threshold_sec field to rebalancer config
- [ ] Add default value (e.g., 30 seconds)
- [ ] Add validation for threshold (must be positive)
- [ ] Document configuration option

## Phase 3: Add Staleness Check Method (verify: method works)
- [ ] Add is_stale method to Quote struct
- [ ] Method takes threshold parameter
- [ ] Returns true if age > threshold
- [ ] Add unit tests for staleness detection

## Phase 4: Integrate into Rebalancer (verify: rebalancer checks staleness)
- [ ] Add staleness check before order submission in execution.rs
- [ ] Abort rebalance if any quote is stale
- [ ] Log stale quote detection with symbol and age
- [ ] Return StaleQuote error from execution

## Phase 5: Add Integration Test (verify: test passes)
- [ ] Create test using MockTws F4 failure mode
- [ ] Inject stale quote scenario
- [ ] Assert rebalance aborts on stale data
- [ ] Verify staleness threshold is enforced
- [ ] Test with both fresh and stale quotes

## Phase 6: Documentation (verify: docs updated)
- [ ] Document Quote timestamp field
- [ ] Document staleness threshold configuration
- [ ] Document staleness check behavior
- [ ] Add comments explaining why stale quotes are dangerous